<?php
/**
 * Created by PhpStorm.
 * User: luomo
 * Date: 2019-03-14
 * Time: 13:41
 */

namespace Biz\scraper;

use Biz\cache\wiki\TbkGoods;
use Biz\cache\wiki\TbkUrl;
use Biz\model\wiki\Wiki;
use Biz\model\wiki\WikiContent;
use Biz\module\Classes\WikiClean\Run;
use Biz\pockets\callback\resultCallBack;
use Biz\pockets\callback\taskCallback;
use Biz\service\wiki\AdmWiki;
use Biz\tools\DingDanXia;
use Biz\tools\JdUnion;
use Biz\tools\OneBound;
use Biz\tools\RealUrl;
use Biz\tools\ShenJian;
use Biz\tools\Tbk3rd;
use Biz\tools\TbkUnion;
use Doraemon\amqp\ScraperQueue;
use Doraemon\model\Store\ShenJianGoods as mShenJianGoods;
use Doraemon\model\Store\ShenJianGoodsSourceData as mShenJianGoodsSourceData;
use Doraemon\model\Store\ShenJianMap as mShenJianMap;
use Doraemon\pockets\constInterface\ApiCode;
use Doraemon\tools\Log;
use Doraemon\tools\Youzan;
use function GuzzleHttp\Psr7\parse_query;

class GoodsInfo
{
    const SCRAPER_RESULT_SUCCESS = 1;
    const SCRAPER_RESULT_FAIL = 0;

    const USE_DING_DAN_XIA = 1;
    use resultCallBack;

    /**
     * @param $sign 请求标识，回调时会原样ƒ返回
     * @param string $content 抓取链接 链接或二维码
     * @param $callback 执行完成后的回调方法
     * @return true 添加任务结果
     * 回调函数返回结果格式
     * 返回结果格式
     * [
     *  'code'=>1// 1为抓取成功 0为抓取失败，
     *   'data'=>[
     *      'id'=>123//res_id
     *   ]
     * ]
     *
     * @throws \Exception
     */
    public static function addTask($sign, string $content, $callback)
    {
        if (!new $callback instanceof taskCallback) {
            throw new \Exception($callback . " must instanceof " . taskCallback::class, ApiCode::API_CODE_EXCEPTION);
        }
        try {
            //入队列
            ScraperQueue::insertQueue(json_encode([
                __CLASS__,
                'scraperData'
            ]), [
                'sign' => $sign,
                'content' => $content,
                'callback' => $callback
            ], ScraperQueue::QUEUE_SCRAPER);

        } catch (\Exception $e) {
            Log::error("入队列失败", [
                $sign,
                $content,
                $e
            ]);
        }
        return true;
    }

    /**
     * @param string $content
     * @param callable $callback
     * @param $params
     * @return mixed
     * @throws \Exception
     */
    public static function addTaskCopy(string $content, $callback, $params = [])
    {
        $url = self::getUrl($content);
        if (!$url) {
            throw new \Exception('解析地址为空');
        }
        $urlType = RealUrl::getUrlType($url);
        if (!$urlType) {
            throw new \Exception('解析地址类型为空');
        }
        $itemId = RealUrl::getItemId($url, $urlType);
        if (!$itemId) {
            throw new \Exception('商品id不存在');
        }

        self::scraperDataCleanData([
            'url' => $url,
            'params' => $params,
            'callback' => $callback
        ]);

        return false;
        //入队列
        ScraperQueue::insertQueue(json_encode([
            __CLASS__,
            'scraperDataCleanData'
        ]), [
            'url' => $url,
            'params' => $params,
            'callback' => $callback
        ], ScraperQueue::QUEUE_SCRAPER);
    }

    public static function addReloadTask($params = [])
    {
        try {
            //入队列
            ScraperQueue::insertQueue(json_encode([
                AdmWiki::class,
                'scraperReloadData'
            ]), [
                'params' => $params,
            ], ScraperQueue::QUEUE_SCRAPER);

        } catch (\Exception $e) {
            Log::error("reload task 入队列失败", [
                $params,
                $e
            ]);
        }
        return true;
    }

    public static function addOneBoundTask($wikiId)
    {
        $params = ['id' => $wikiId];
        try {
            //入队列
            ScraperQueue::insertQueue(json_encode([
                AdmWiki::class,
                'scraperUpdateByOneBound'
            ]), [
                'params' => $params
            ], ScraperQueue::QUEUE_SCRAPER);

        } catch (\Exception $e) {
            Log::error("OneBound task 入队列失败", [
                $params,
                $e
            ]);
        }
        return true;
    }

    /**
     * 清洗抓取数据后执行后续操作
     * @param array $args
     * @throws \Exception
     */
    public static function scraperDataCleanData($args)
    {
        try {
            $url = isset($args['url']) ? $args['url'] : '';
            $callback = isset($args['callback']) ? $args['callback'] : '';
            $params = isset($args['params']) ? $args['params'] : [];


            //抓取数据
            $goodsInfo = ShenJian::getGoodsInfo($url);

            if (!$goodsInfo) {
                throw new \Exception('抓取数据失败');
            }

            $urlType = RealUrl::getUrlType($url);
            $resId = self::saveScraperData($goodsInfo, $urlType);

            if (!$resId) {
                throw new \Exception('存储数据失败');
            }

            //添加map记录
            $params['content'] = $url;
            self::addRecord($params, $resId, $url); // 如果想知道哪些链接没有抓取到数据的话，直接到map表查看res_id为0的数据

            //清洗数据
            $cleanData = Run::run($result = [
                'code' => self::SCRAPER_RESULT_SUCCESS,
                'data' => ['id' => $resId]
            ]);

            //清洗数据结构校验
            if (!isset($cleanData['goods'])) {
                throw new \Exception('清洗数据结构有误goods');
            }
            $cleaningData = $cleanData['goods'];
            if (!isset($cleaningData['type'])) {
                throw new \Exception('清洗数据结构有误type');
            }
            $channel = \Biz\module\Classes\wiki\Wiki::getChannel($cleaningData['type']);
            if (!$channel) {
                throw new \Exception('清洗数据渠道有误,type:' . $cleaningData['type']);
            }
            $cleaningData['channel'] = $channel;
            $params['cleanData'] = $cleaningData;

            if (is_callable($callback)) {
                call_user_func($callback, $params);
            }
            Log::info("清洗抓取数据后执行后续操作", compact('args'));
        } catch (\Exception $e) {
            $trace = [
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'msg' => $e->getMessage(),
            ];
            Log::error("清洗抓取数据后执行后续操作", compact('trace', 'args'));
        }
    }

    /**
     * @param $params
     * @return bool
     */
    public static function scraperData($params)
    {
        $url = self::getUrl($params['content']);
        if (!$url) {
            $result['code'] = self::SCRAPER_RESULT_FAIL;
        } else {
            $resId = 0;
            $urlType = RealUrl::getUrlType($url);
            if ($urlType) {
                $itemId = RealUrl::getItemId($url, $urlType);
                if ($itemId) {
                    $resId = mShenJianGoods::getInfo($itemId, $urlType);
                    if ($resId) {
                        //重复爬取请求
                        $result = [
                            'code' => self::SCRAPER_RESULT_SUCCESS,
                            'data' => ['id' => $resId]
                        ];
                    } else {
                        $result = [];
                        $goodsInfo = ShenJian::getGoodsInfo($url);
                        if ($goodsInfo) {
                            $resId = self::saveScraperData($goodsInfo, $urlType);
                            if ($resId) {
                                $result = [
                                    'code' => self::SCRAPER_RESULT_SUCCESS,
                                    'data' => ['id' => $resId]
                                ];
                            } else {
                                $result['code'] = self::SCRAPER_RESULT_FAIL;
                            }
                        } else {
                            $result['code'] = self::SCRAPER_RESULT_FAIL;
                        }
                    }

                } else {
                    $result['code'] = self::SCRAPER_RESULT_FAIL;
                }
            } else {
                $result['code'] = self::SCRAPER_RESULT_FAIL;
            }
            self::addRecord($params, $resId, $url); // 如果想知道哪些链接没有抓取到数据的话，直接到map表查看res_id为0的数据
        }

        return self::_resultCallBack($result, $params);
    }

    public static function getUrl($content)
    {
        $result = false;
        $url = '';
        if (filter_var($content, FILTER_VALIDATE_URL)) {
            //内容为链接的直接处理
            $url = $content;
        } else {
            $covertData = TbkUnion::tpwdConvert($content);
            if ($covertData && $covertData['origin_url']) {
                $url = $covertData['origin_url'];
                $clickUrl = $covertData['click_url'];
                $urlHost = parse_url($url, PHP_URL_HOST);
                if ($urlHost == RealUrl::ULAND_TAOBAO_HOST && !empty($clickUrl)) {
                    $url = $clickUrl;
                }
            } else {
                $res = self::checkTkl($content);
                if ($res) {
                    //尝试淘口令转换
                    $url = Tbk3rd::tklDecrypt($res);
                }
                if (empty($url)) {
                    //尝试正则转换
                    $url = RealUrl::regexUrl($content);
                }
            }
        }
        if ($url) {
            //获取链接最终指向地址，处理重定向及其js跳转
            $result = RealUrl::getRealUrl($url);
            if (!$result && self::USE_DING_DAN_XIA) {
                $result = DingDanXia::getTklUrl($content);
            }
        }
        if (!$result) {
            Log::wiki_geturl_debug('获取url失败', $content);
        }
        return $result;
    }

    public static function saveScraperData($goodsInfo, $urlType)
    {
        switch ($urlType) {
            case RealUrl::URL_TYPE_TAOBAO:
                $formatData = self::formatTaoBaoItem($goodsInfo);
                break;
            case RealUrl::URL_TYPE_TMALL:
                $formatData = self::formatTmallItem($goodsInfo);
                break;
            case RealUrl::URL_TYPE_JD:
                $formatData = self::formatJdItem($goodsInfo);
                break;
        }
        $resId = mShenJianGoods::addRecord($formatData['formatData']);
        if ($resId) {
            $formatData['shenjianGoodsSourceData']['shenjian_goods_id'] = $resId;
            mShenJianGoodsSourceData::addRecord($formatData['shenjianGoodsSourceData']);
            return $resId;
        }
    }

    private static function getBrandFromParams($params)
    {
        $brand = "";
        foreach ($params as $param) {
            if ($param['label'] == "品牌") {
                $brand = $param['value'];
                break;
            }
        }
        return $brand;
    }

    private static function getPriceFormOriginalPrice($originalPrice)
    {
        $originalPriceData = array_map('trim', explode("-", $originalPrice));
        $priceData = [
            'original_min_price' => $originalPriceData[0],
            'original_max_price' => isset($originalPriceData[1]) ? $originalPriceData[1] : $originalPriceData[0]
        ];
        return $priceData;
    }

    private static function formatTaoBaoItem($sourceData)
    {
        if (isset($sourceData['current_price']) && $sourceData['current_price']) {
            $priceData = self::getPriceFormOriginalPrice($sourceData['current_price']);
        } else {
            $priceData = self::getPriceFormOriginalPrice($sourceData['original_price']);
        }

        $formatData = [
            'type' => RealUrl::URL_TYPE_TAOBAO,
            'category_id' => $sourceData['category_id'],
            'item_id' => $sourceData['product_id'],
            'name' => $sourceData['name'],
            'shop_id' => $sourceData['shop_id'],
            'shop_name' => $sourceData['shop_name'],
            'original_min_price' => $priceData['original_min_price'],
            'original_max_price' => $priceData['original_max_price'],
            'brand' => self::getBrandFromParams($sourceData['params']),
            'stock' => $sourceData['stock'],
            'shipping_address' => $sourceData['shipping_address'],
        ];

        $shenjianGoodsSourceData = [
            'item_id' => $sourceData['product_id'],
            'type' => RealUrl::URL_TYPE_TAOBAO,
            'source_data' => json_encode($sourceData, JSON_UNESCAPED_UNICODE),
            'images' => json_encode($sourceData['images']),
            'params' => json_encode($sourceData['params'], JSON_UNESCAPED_UNICODE),
            'sku' => json_encode([
                'sku' => $sourceData['sku'],
                'product_sku_detail' => $sourceData['product_sku_detail']
            ], JSON_UNESCAPED_UNICODE),
        ];

        return compact('formatData', 'shenjianGoodsSourceData');
    }

    private static function formatTmallItem($sourceData)
    {
        if (isset($sourceData['current_price']) && $sourceData['current_price']) {
            $priceData = self::getPriceFormOriginalPrice($sourceData['current_price']);
        } else {
            $priceData = self::getPriceFormOriginalPrice($sourceData['original_price']);
        }
        $formatData = [
            'type' => RealUrl::URL_TYPE_TMALL,
            'category_id' => isset($sourceData['category_id']) ? $sourceData['category_id'] : '0',
            'item_id' => $sourceData['product_id'],
            'name' => $sourceData['name'],
            'shop_id' => $sourceData['shop_id'],
            'shop_name' => $sourceData['shop_name'],
            'original_min_price' => $priceData['original_min_price'],
            'original_max_price' => $priceData['original_max_price'],
            'brand' => self::getBrandFromParams($sourceData['params']),
            'stock' => isset($sourceData['stock']) ? $sourceData['stock'] : 0,
            'shipping_address' => isset($sourceData['shipping_address']) ? $sourceData['shipping_address'] : "",
        ];

        $shenjianGoodsSourceData = [
            'item_id' => $sourceData['product_id'],
            'type' => RealUrl::URL_TYPE_TAOBAO,
            'source_data' => json_encode($sourceData, JSON_UNESCAPED_UNICODE),
            'images' => json_encode($sourceData['images']),
            'params' => json_encode($sourceData['params'], JSON_UNESCAPED_UNICODE),
            'sku' => json_encode([
                'sku' => $sourceData['sku'],
                'product_sku_detail' => $sourceData['product_sku_detail']
            ], JSON_UNESCAPED_UNICODE),
        ];

        return compact('formatData', 'shenjianGoodsSourceData');

    }

    private static function formatJdItem($sourceData)
    {
        $formatData = [
            'type' => RealUrl::URL_TYPE_JD,
            'category_name' => json_encode($sourceData['categories'], JSON_UNESCAPED_UNICODE),
            'item_id' => $sourceData['product_id'],
            'name' => $sourceData['name'],
            'shop_id' => $sourceData['shop_id'],
            'shop_name' => $sourceData['shop_name'],
            'original_min_price' => $sourceData['current_price'],
            'original_max_price' => $sourceData['current_price'],
            'brand' => $sourceData['brand'],
        ];

        $shenjianGoodsSourceData = [
            'item_id' => $sourceData['product_id'],
            'type' => RealUrl::URL_TYPE_TAOBAO,
            'source_data' => json_encode($sourceData),
            'images' => json_encode($sourceData['images']),
            'params' => json_encode($sourceData['params']),
            'sku' => json_encode([
                'product_sku_detail' => $sourceData['product_sku_detail']
            ])
        ];

        return compact('formatData', 'shenjianGoodsSourceData');

    }

    public static function getGoodsInfo($content, $goodsDesc = true)
    {
        $info = [];
        $unionInfoArr = self::getUnionInfo($content);
        $itemId = 0;
        $channelType = 0;
        if ($unionInfoArr) {
            $unionInfo = $unionInfoArr['union_info'];
            $channelInfo = $unionInfoArr['channel_info'];
            $itemId = $channelInfo['channel_spu_id'];
            $channelType = $channelInfo['channel_type'];
            $useDingDanXia = self::useDingDanXia($unionInfo);
            if ($useDingDanXia) {
                if ($unionInfo) {
                    //$dingDanXiaGoodsInfo = DingDanXia::getTbkItemInfo($channelType, $itemId);
                } else {
                    //$dingDanXiaGoodsInfo = self::getDingDanXiaInfo($itemId, $channelType, $goodsDesc);
                }
                $info = $unionInfo;
                //$info = self::formatDingDanXiaGoodsInfo($info, $dingDanXiaGoodsInfo);
                if (empty($info) || empty($info['title']) || empty($info['cover_img']) || empty($info['content'])) {
                    $oneBoundInfo = OneBound::getTaoBaoItemInfo($itemId, $channelType);
                    $info = self::formatOneBoundInfo($info, $oneBoundInfo);
                }
            }
        }
        return [$info, $itemId, $channelType];
    }

    public static function formatDingDanXiaGoodsInfo($info, $dingDanXiaGoodsInfo)
    {
        if ($dingDanXiaGoodsInfo) {
            if (!isset($info['channel_spu_id']) || empty($info['channel_spu_id'])) {
                $info['channel_spu_id'] = $dingDanXiaGoodsInfo['channel_spu_id'] ?: '';
            }
            if (!isset($info['channel_type']) || empty($info['channel_type'])) {
                $info['channel_type'] = $dingDanXiaGoodsInfo['channel_type'] ?: '';
            }
            if (!isset($info['title']) || empty($info['title'])) {
                $info['title'] = $dingDanXiaGoodsInfo['title'] ?: '';
            }
            if (!isset($info['channel_seller_id']) || empty($info['channel_seller_id'])) {
                $info['channel_seller_id'] = isset($dingDanXiaGoodsInfo['channel_seller_id']) ? abs($dingDanXiaGoodsInfo['channel_seller_id']) : 0;
            }
            if (!isset($info['channel_shop_id']) || empty($info['channel_shop_id'])) {
                $info['channel_shop_id'] = $dingDanXiaGoodsInfo['channel_shop_id'] ?: 0;
            }
            if (!isset($info['channel_shop_name']) || empty($info['channel_shop_name'])) {
                $info['channel_shop_name'] = $dingDanXiaGoodsInfo['channel_shop_name'] ?: '';
            }
            if (!isset($info['min_price']) || empty($info['min_price'])) {
                $info['min_price'] = $dingDanXiaGoodsInfo['min_price'] ?: 0;
            }
            if (!isset($info['max_price']) || empty($info['max_price'])) {
                $info['max_price'] = $dingDanXiaGoodsInfo['max_price'] ?: 0;
            }
            //价格特殊处理，因为淘宝联盟返回的价格没有区间
            if (bccomp($info['min_price'], $info['max_price'], 2) == 0) {
                $info['min_price'] = $dingDanXiaGoodsInfo['min_price'] ?: $info['min_price'];
                $info['max_price'] = $dingDanXiaGoodsInfo['max_price'] ?: $info['max_price'];
            }
            if (!isset($info['channel_category_name']) || empty($info['channel_category_name'])) {
                $info['channel_category_name'] = $dingDanXiaGoodsInfo['channel_category_name'] ?: '';
            }
            if (!isset($info['channel_brand']) || empty($info['channel_brand'])) {
                $info['channel_brand'] = $dingDanXiaGoodsInfo['channel_brand'] ?: '';
            }
            if (!isset($info['cover_img']) || empty($info['cover_img'])) {
                $info['cover_img'] = $dingDanXiaGoodsInfo['cover_img'] ?: '';
            }
            if (!isset($info['imgs']) || empty($info['imgs'])) {
                $info['imgs'] = $dingDanXiaGoodsInfo['imgs'] ?: '';
            }
            if (!isset($info['content']) || empty($info['content'])) {
                $info['content'] = $dingDanXiaGoodsInfo['content'] ?: '';;
            }
            if (!isset($info['channel_spu_status']) && isset($dingDanXiaGoodsInfo['channel_spu_status'])) {
                $info['channel_spu_status'] = ($dingDanXiaGoodsInfo['channel_spu_status'] <= 0) ? 0 : 1;
            }
            if (!isset($info['tags']) || empty($info['tags'])) {
                $info['tags'] = isset($dingDanXiaGoodsInfo['tags']) ? $dingDanXiaGoodsInfo['tags'] : '';
            }
        }
        return $info;
    }

    public static function formatOneBoundInfo($info, $oneBoundInfo)
    {
        if ($oneBoundInfo) {
            if (!isset($info['channel_spu_id']) || empty($info['channel_spu_id'])) {
                $info['channel_spu_id'] = $oneBoundInfo['channel_spu_id'] ?: $info['channel_spu_id'];
            }
            if (!isset($info['channel_type']) || empty($info['channel_type'])) {
                $info['channel_type'] = $oneBoundInfo['channel_type'] ?: $info['channel_type'];
            }
            if (!isset($info['title']) || empty($info['title'])) {
                $info['title'] = $oneBoundInfo['title'] ?: $info['title'];
            }
            if (!isset($info['channel_seller_id']) || empty($info['channel_seller_id'])) {
                $info['channel_seller_id'] = isset($oneBoundInfo['channel_seller_id']) ? abs($oneBoundInfo['channel_seller_id']) : $info['channel_seller_id'];
            }
            if (!isset($info['channel_shop_id']) || empty($info['channel_shop_id'])) {
                $info['channel_shop_id'] = $oneBoundInfo['channel_shop_id'] ?: ($info['channel_shop_id'] ?? 0);
            }
            if (!isset($info['channel_shop_name']) || empty($info['channel_shop_name'])) {
                $info['channel_shop_name'] = $oneBoundInfo['channel_shop_name'] ?: ($info['channel_shop_name'] ?? '');
            }
            if (!isset($info['min_price']) || empty($info['min_price'])) {
                $info['min_price'] = ($oneBoundInfo['min_price'] > 0) ? $oneBoundInfo['min_price'] : $info['min_price'];
            }
            if (!isset($info['max_price']) || empty($info['max_price'])) {
                $info['max_price'] = ($oneBoundInfo['max_price'] > 0) ? $oneBoundInfo['max_price'] : $info['max_price'];
            }
            //价格特殊处理，因为淘宝联盟返回的价格没有区间
            if (bccomp($info['min_price'], $info['max_price'], 2) == 0) {
                $info['min_price'] = ($oneBoundInfo['min_price'] > 0) ? $oneBoundInfo['min_price'] : $info['min_price'];
                $info['max_price'] = ($oneBoundInfo['max_price'] > 0) ? $oneBoundInfo['max_price'] : $info['max_price'];
            }
            if (!isset($info['channel_category_name']) || empty($info['channel_category_name'])) {
                $info['channel_category_name'] = $oneBoundInfo['channel_category_name'] ?: ($info['channel_category_name'] ?? '');
            }
            if (!isset($info['channel_brand']) || empty($info['channel_brand'])) {
                $info['channel_brand'] = $oneBoundInfo['channel_brand'] ?: ($info['channel_brand'] ?? '');
            }
            if (!isset($info['cover_img']) || empty($info['cover_img'])) {
                $info['cover_img'] = $oneBoundInfo['cover_img'] ?: ($info['cover_img'] ?? '');
            }
            if (!isset($info['imgs']) || empty($info['imgs'])) {
                $info['imgs'] = $oneBoundInfo['imgs'] ?: $info['imgs'];
            }
            if (!isset($info['content']) || empty($info['content'])) {
                $info['content'] = $oneBoundInfo['content'] ?: $info['content'];;
            }
            if (!isset($info['tags']) || empty($info['tags'])) {
                $info['tags'] = isset($oneBoundInfo['tags']) ? $oneBoundInfo['tags'] : $info['tags'];
            }
        }
        return $info;
    }

    /**
     * 获取淘宝商品Id
     * @param $content 淘宝链接、淘口令
     * @return false|int|mixed|string|void
     */
    public static function getTaoBaoItemId($content)
    {
        $url = self::getUrl($content);
        $urlType = RealUrl::getUrlType($url);
        $itemId = RealUrl::getItemId($url, $urlType);
        if (in_array($urlType, [RealUrl::URL_TYPE_TAOBAO, RealUrl::URL_TYPE_TMALL])) {
            return $itemId;
        } else {
            return false;
        }
    }

    /**
     * @param $content 商品url
     * @return array
     */
    public static function getUnionInfo($content)
    {
        $url = self::getUrl($content);
        Log::wiki_content_info('原内容解析结果', [
            $url,
            $content
        ]);

        if (!$url) {
            $urlType = RealUrl::getUrlType($content);
            if (in_array($urlType, [RealUrl::URL_TYPE_XIAOEPINPIN, RealUrl::URL_TYPE_AMAZON, RealUrl::URL_TYPE_XIAOMIYOUPIN, RealUrl::URL_TYPE_SAMSUNGESHOP])) {
                $spuId = '';
                switch ($urlType) {
                    case RealUrl::URL_TYPE_XIAOEPINPIN:
                        $query = parse_url($content, PHP_URL_QUERY);
                        $request = parse_query($query);
                        $spuId = $request['spuId'] ?? 0;
                        $itemInfo = Wiki::get('*', ['channel' => $urlType, 'channel_spu_id' => $spuId]);
                        break;
                    case RealUrl::URL_TYPE_AMAZON:
                        $content = parse_url($content, PHP_URL_PATH);
                        $arr = explode("/", $content);
                        $spuId = end($arr);
                        $itemInfo = Wiki::get('*', ['channel' => $urlType, 'channel_jump_params' => $spuId]);
                        break;
                    case RealUrl::URL_TYPE_XIAOMIYOUPIN:
                        $query = parse_url($content, PHP_URL_QUERY);
                        $request = parse_query($query);
                        if ($to = $request['to'] ?? '') {
                            $to = urldecode($to);
                            $query = parse_url($to, PHP_URL_QUERY);
                            $request = parse_query($query);
                        }
                        $spuId = $request['gid'] ?? 0;
                        $itemInfo = Wiki::get('*', ['channel' => $urlType, 'channel_spu_id' => $spuId]);
                        break;
                    case RealUrl::URL_TYPE_SAMSUNGESHOP:
                        $path = parse_url($content, PHP_URL_PATH);
                        $path = str_replace('/product/', '', $path);
                        $arr = explode('/', $path);
                        $spuId = current($arr);
                        $itemInfo = Wiki::get('*', ['channel' => $urlType, 'channel_jump_params' => $spuId]);
                        break;
                }

                if (empty($itemInfo)) return [];
                $itemContentInfo = WikiContent::getByWhere(['wiki_id' => $itemInfo['id']]);
                return [
                    'channel_info' => [
                        'channel_spu_id' => !empty($itemInfo['channel_spu_id']) ? $itemInfo['channel_spu_id'] : '',
                        'channel_type' => $urlType
                    ],
                    'union_info' => [
                        'title' => !empty($itemInfo['title']) ? $itemInfo['title'] : '',
                        'channel' => !empty($itemInfo['channel']) ? $itemInfo['channel'] : $urlType,
                        'channel_type' => $urlType,
                        'channel_shop_id' => !empty($itemInfo['channel_shop_id']) ? $itemInfo['channel_shop_id'] : 0,
                        'channel_shop_name' => !empty($itemInfo['channel_shop_name']) ? $itemInfo['channel_shop_name'] : '',
                        'channel_spu_id' => !empty($itemInfo['channel_spu_id']) ? $itemInfo['channel_spu_id'] : '',
                        'channel_brand' => '',
                        'channel_jump_params' => !empty($itemInfo['channel_jump_params']) ? $itemInfo['channel_jump_params'] : '',
                        'channel_category_name' => !empty($itemInfo['channel_category_name']) ? $itemInfo['channel_category_name'] : '',
                        'cover_img' => $itemInfo['cover_img'],
                        'min_price' => !empty($itemInfo['min_price']) ? $itemInfo['min_price'] : '',
                        'max_price' => !empty($itemInfo['max_price']) ? $itemInfo['max_price'] : '',
                        'imgs' => $itemContentInfo['imgs'] ?? '',
                        'content' => $itemContentInfo['content'] ?? '',
                    ]
                ];
            }
        } else {
            $urlType = RealUrl::getUrlType($url);
            if ($urlType) {
                if ($urlType == RealUrl::URL_TYPE_YOUZAN) {
                    $itemInfo = Youzan::getGoodsInfoByUrl($url);
                    if ($itemInfo) {
                        return [
                            'channel_info' => [
                                'channel_spu_id' => !empty($itemInfo['channel_spu_id']) ? $itemInfo['channel_spu_id'] : '',
                                'channel_type' => $urlType
                            ],
                            'union_info' => [
                                'title' => !empty($itemInfo['title']) ? $itemInfo['title'] : '',
                                'channel' => !empty($itemInfo['channel']) ? $itemInfo['channel'] : $urlType,
                                'channel_type' => $urlType,
                                'channel_shop_id' => !empty($itemInfo['channel_shop_id']) ? $itemInfo['channel_shop_id'] : 0,
                                'channel_shop_name' => !empty($itemInfo['channel_shop_name']) ? $itemInfo['channel_shop_name'] : '',
                                'channel_spu_id' => !empty($itemInfo['channel_spu_id']) ? $itemInfo['channel_spu_id'] : '',
                                'channel_jump_params' => !empty($itemInfo['channel_jump_params']) ? $itemInfo['channel_jump_params'] : '',
                                'channel_category_name' => !empty($itemInfo['channel_category_name']) ? $itemInfo['channel_category_name'] : '',
                                'cover_img' => $itemInfo['cover_img'],
                                'min_price' => !empty($itemInfo['min_price']) ? $itemInfo['min_price'] : '',
                                'max_price' => !empty($itemInfo['max_price']) ? $itemInfo['max_price'] : '',
                                'imgs' => !empty($itemInfo['imgs']) ? json_encode($itemInfo['imgs'], JSON_UNESCAPED_UNICODE) : '',
                                'content' => !empty($itemInfo['content']) ? $itemInfo['content'] : '',
                            ]
                        ];
                    }
                } else {
                    $itemId = RealUrl::getItemId($url, $urlType);
                    if ($itemId) {
                        if ($urlType == RealUrl::URL_TYPE_TAOBAO || $urlType == RealUrl::URL_TYPE_TMALL) {
                            $itemInfo = TbkUnion::getItemInfo($itemId);
                            if ($itemInfo) {
                                TbkGoods::addGoods($itemId);
                                $tbkDgOpMaterialOptionalData = $itemInfo['item_url'] ? TbkUnion::tbkDgOpMaterialOptional($itemInfo['item_url']) : [];
                                $tbkDgOpMaterialOptionalInfo = $tbkDgOpMaterialOptionalData[0] ?? [];
                                $clickUrl = $tbkDgOpMaterialOptionalInfo['url'] ?? '';
                                if ($clickUrl && !TbkUrl::getItem($itemId)) {
                                    TbkUrl::setUrl($itemId, $clickUrl);
                                }
                                $coverImgs = !empty($itemInfo['pict_url']) ? $itemInfo['pict_url'] : '';
                                $imgs[] = $coverImgs;
                                $imgs = array_merge($imgs, $itemInfo['small_images']['string'] ?? []);
                                $imgs = array_filter(array_unique($imgs));
                                //卖家类型，0表示集市，1表示商城，3表示特价版
                                if (isset($itemInfo['user_type'])) {
                                    $urlType = ($itemInfo['user_type'] == 1) ? RealUrl::URL_TYPE_TMALL : RealUrl::URL_TYPE_TAOBAO;
                                }
                                return [
                                    'channel_info' => [
                                        'channel_spu_id' => $itemId,
                                        'channel_type' => $urlType
                                    ],
                                    'union_info' => [
                                        'title' => !empty($itemInfo['title']) ? $itemInfo['title'] : '',
                                        'channel_type' => $urlType,
                                        'channel_seller_id' => 0,//!empty($itemInfo['seller_id']) ? $itemInfo['seller_id'] : 0,//卖家id 不在使用，淘宝客已经使用了混淆seller_id 脱敏处理后的数字代码（非原卖家id）
                                        'channel_shop_id' => 0,//淘宝客联盟未提供
                                        'channel_shop_name' => !empty($itemInfo['nick']) ? $itemInfo['nick'] : '',
                                        'channel_spu_id' => $itemId,
                                        'channel_category_name' => !empty($itemInfo['cat_name']) ? $itemInfo['cat_name'] : '',
                                        'cover_img' => $coverImgs,
                                        'min_price' => !empty($itemInfo['zk_final_price']) ? $itemInfo['zk_final_price'] : '',
                                        'max_price' => !empty($itemInfo['zk_final_price']) ? $itemInfo['zk_final_price'] : '',
                                        'imgs' => $imgs ? json_encode($imgs, JSON_UNESCAPED_UNICODE) : '',
                                        'addtime' => date('Y-m-d H:i:s'),
                                        'edittime' => date('Y-m-d H:i:s'),
                                        'channel_spu_status' => 1,
                                        'white_image' => $tbkDgOpMaterialOptionalInfo['white_image'] ?? '',//白底图
                                        'simple_title' => $tbkDgOpMaterialOptionalInfo['short_title'] ?? ''//商品短标题
                                    ]
                                ];
                            } else {
                                TbkGoods::delGoods($itemId);
                            }
                        } else if ($urlType == RealUrl::URL_TYPE_JD) {

                            $itemInfo = JdUnion::getItemInfo($itemId);
                            if ($itemInfo) {
                                $content = '';
                                if (isset($itemInfo['detailImages']) && $itemInfo['detailImages']) {
                                    foreach ($itemInfo['detailImages'] as $detailImgRow) {
                                        $parseUrlArr = parse_url($detailImgRow);
                                        $detailImgUrl = 'https://' . $parseUrlArr['host'] . $parseUrlArr['path'];
                                        $content .= '<img src="' . $detailImgUrl . '">';
                                    }
                                }
                                $price = !empty($itemInfo['unitPrice']) ? $itemInfo['unitPrice'] : 0;
                                if (!$price) {
                                    $priceArr = JdUnion::getJDPrice($itemId);
                                    $price = ($priceArr && isset($priceArr[$itemId])) ? $priceArr[$itemId] : 0;
                                }
                                $coverImg = !empty($itemInfo['imgUrl']) ? $itemInfo['imgUrl'] : '';
                                $coverImg = self::parseImgUrl($coverImg);
                                $imgs = !empty($itemInfo['imageList']) ? $itemInfo['imageList'] : [];
                                $imgs = self::parseImgsUrl($imgs);
                                if ($imgs && !$coverImg) {
                                    $coverImg = $imgs[0];
                                }
                                return [
                                    'channel_info' => [
                                        'channel_spu_id' => !empty($itemInfo['skuId']) ? $itemInfo['skuId'] : '',
                                        'channel_type' => $urlType
                                    ],
                                    'union_info' => [
                                        'title' => !empty($itemInfo['goodsName']) ? $itemInfo['goodsName'] : '',
                                        'channel_type' => $urlType,
                                        'channel_spu_id' => !empty($itemInfo['skuId']) ? $itemInfo['skuId'] : '',
                                        'channel_category_name' => !empty($itemInfo['cidName']) ? $itemInfo['cidName'] : '',
                                        'channel_shop_id' => !empty($itemInfo['shopId']) ? $itemInfo['shopId'] : '',
                                        'channel_shop_name' => '',//京东联盟api 未提供
                                        'cover_img' => $coverImg,
                                        'min_price' => $price,
                                        'max_price' => $price,
                                        'imgs' => !empty($imgs) ? json_encode($imgs, JSON_UNESCAPED_UNICODE) : '',
                                        'content' => $content,
                                        'addtime' => date('Y-m-d H:i:s'),
                                        'edittime' => date('Y-m-d H:i:s'),
                                        'channel_spu_status' => isset($itemInfo['skuStatus']) ? $itemInfo['skuStatus'] : 1,
                                    ]
                                ];
                            }
                        }

                        return [
                            'channel_info' => [
                                'channel_spu_id' => $itemId,
                                'channel_type' => $urlType
                            ],
                            'union_info' => [
                            ]
                        ];
                    }
                }
            }
        }

        return [];
    }

    public static function useDingDanXia($info)
    {
        if ($info) {//如果union 查询到了信息
            $mustKeys = ['title', 'channel_shop_id', 'channel_shop_name', 'min_price', 'max_price', 'cover_img', 'imgs', 'content'];
            $useDingDanXia = false;
            foreach ($mustKeys as $field) {
                if (!isset($unionInfo[$field]) || empty($unionInfo[$field])) {
                    $useDingDanXia = true;
                    break;
                }
            }
        } else {
            $useDingDanXia = true;
        }
        $useDingDanXia = ($useDingDanXia && self::USE_DING_DAN_XIA) ? true : false;
        return $useDingDanXia;
    }

    public static function getDingDanXiaInfo($itemId, $type, $goodsDesc = true)
    {
        if (!in_array($type, [RealUrl::URL_TYPE_TAOBAO, RealUrl::URL_TYPE_TMALL, RealUrl::URL_TYPE_JD])) {
            return [];
        }
        $dingDanXiaGoodsInfo = DingDanXia::getInfo($type, $itemId, $goodsDesc);
        return $dingDanXiaGoodsInfo;
    }

    public static function getGoodsInfoPrice($channelType, $itemId)
    {
        $result = [];
        if ($channelType == RealUrl::URL_TYPE_TAOBAO || $channelType == RealUrl::URL_TYPE_TMALL) {
            $itemInfo = TbkUnion::getItemInfo($itemId);
            if ($itemInfo) {
                $result['min_price'] = !empty($itemInfo['zk_final_price']) ? $itemInfo['zk_final_price'] : '';
                $result['max_price'] = !empty($itemInfo['zk_final_price']) ? $itemInfo['zk_final_price'] : '';
            }
            if (self::USE_DING_DAN_XIA) {
                $dingDanXiaGoodsInfo = DingDanXia::getInfo($channelType, $itemId, false);
                if ($dingDanXiaGoodsInfo) {
                    if (!isset($result['min_price']) || empty($result['min_price'])) {
                        $result['min_price'] = ($dingDanXiaGoodsInfo['min_price'] > 0) ? $dingDanXiaGoodsInfo['min_price'] : 0;
                    }
                    if (!isset($result['max_price']) || empty($result['max_price'])) {
                        $result['max_price'] = ($dingDanXiaGoodsInfo['max_price'] > 0) ? $dingDanXiaGoodsInfo['max_price'] : 0;
                    }
                    if (bccomp($result['min_price'], $result['max_price'], 2) == 0) {
                        $result['min_price'] = ($dingDanXiaGoodsInfo['min_price'] > 0) ? $dingDanXiaGoodsInfo['min_price'] : $result['min_price'];
                        $result['max_price'] = ($dingDanXiaGoodsInfo['max_price'] > 0) ? $dingDanXiaGoodsInfo['max_price'] : $result['max_price'];
                    }
                }
            }
            $oneBoundInfo = OneBound::getTaoBaoItemInfo($itemId, $channelType);
            if ($oneBoundInfo) {
                if (!isset($result['min_price']) || empty($result['min_price'])) {
                    $result['min_price'] = ($oneBoundInfo['min_price'] > 0) ? $oneBoundInfo['min_price'] : 0;
                }
                if (!isset($result['max_price']) || empty($result['max_price'])) {
                    $result['max_price'] = ($oneBoundInfo['max_price'] > 0) ? $oneBoundInfo['max_price'] : 0;
                }
                if (bccomp($result['min_price'], $result['max_price'], 2) == 0) {
                    $result['min_price'] = ($oneBoundInfo['min_price'] > 0) ? $oneBoundInfo['min_price'] : $result['min_price'];
                    $result['max_price'] = ($oneBoundInfo['max_price'] > 0) ? $oneBoundInfo['max_price'] : $result['max_price'];
                }
            }
        } else if ($channelType == RealUrl::URL_TYPE_JD) {
            $priceArr = JdUnion::getJDPrice($itemId);
            if ($priceArr && isset($priceArr[$itemId]) && $priceArr[$itemId]) {
                $result = [
                    'min_price' => $priceArr[$itemId],
                    'max_price' => $priceArr[$itemId],
                ];
            } else {
                $itemInfo = JdUnion::getItemInfo($itemId, false);
                if ($itemInfo) {
                    $result = [
                        'min_price' => !empty($itemInfo['unitPrice']) ? $itemInfo['unitPrice'] : '',
                        'max_price' => !empty($itemInfo['unitPrice']) ? $itemInfo['unitPrice'] : '',
                    ];
                }
            }
        }
        return $result;
    }

    public static function getGoodsInfoByResId($resId)
    {
        return mShenJianGoods::getGoodsInfoByResId($resId);
    }

    public static function fixData($params)
    {
        $url = self::getUrl($params['content']);
        if ($url) {
            mShenJianMap::update(['real_url' => $url], ['id' => $params['id']]);
            return 'success';
        } else {
            return 'error';
        }
    }

    private static function addRecord($params, $resId, $url)
    {
        $data = [
            'content' => $params['content'],
            'real_url' => $url
        ];
        mShenJianMap::addRecord($data, $resId);
    }

    /**
     * 根据内容解析淘口令 最终返回淘口令或false
     * @param $content
     * @return bool|mixed
     */
    public static function checkTkl($content)
    {
        preg_match('/([\p{S}])[A-Za-z_0-9]{8,12}([\p{S}])/u', $content, $result);

        if ($result) {
            $result1 = self::utf8ToUnicode($result[1]);
            $result2 = self::utf8ToUnicode($result[2]);

            $digital = $result1 - $result2;

            if (abs($digital) <= 1) {
                return current($result);
            } else {
                Log::wiki_checktkl_debug('check淘口令成功', [$content]);
                Log::wiki_utf8tounicode_debug('计算结果失败', [$content]);
                return false;
            }
        }

        return false;
    }

    private static function utf8ToUnicode($str)
    {
        $ord0 = ord($str[0]);
        if ($ord0 >= 0 && $ord0 <= 127) return $ord0;
        $ord1 = ord($str[1]);
        if ($ord0 >= 192 && $ord0 <= 223) return ($ord0 - 192) * 64 + ($ord1 - 128);
        $ord2 = ord($str[2]);
        if ($ord0 >= 224 && $ord0 <= 239) return ($ord0 - 224) * 4096 + ($ord1 - 128) * 64 + ($ord2 - 128);
        $ord3 = ord($str[3]);
        if ($ord0 >= 240 && $ord0 <= 247) return ($ord0 - 240) * 262144 + ($ord1 - 128) * 4096 + ($ord2 - 128) * 64 + ($ord3 - 128);
        return false;
    }

    private static function parseImgsUrl(array $urlArr)
    {
        $imgUrls = [];
        if ($urlArr) {
            foreach ($urlArr as $url) {
                $imgUrls[] = self::parseImgUrl($url);
            }
        }
        return $imgUrls;
    }

    private static function parseImgUrl($url)
    {
        $imgUrl = '';
        if ($url) {
            $parseUrlArr = parse_url($url);
            $imgUrl = 'https://' . $parseUrlArr['host'] . $parseUrlArr['path'];
        }
        return $imgUrl;
    }
}
